home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume20 / compress / part01 next >
Encoding:
Text File  |  1991-06-26  |  55.0 KB  |  1,921 lines

  1. Newsgroups: comp.sources.misc
  2. From: Dave Mack <csu@alembic.ACS.COM>
  3. Subject:  v20i064:  compress - Compress 4.1, Part01/02
  4. Message-ID: <csm-v20i064=compress.133807@sparky.imd.sterling.com>
  5. X-Md4-Signature: 83b649f6db88775ab02a580bfaf07a6c
  6. Date: Tue, 25 Jun 1991 18:38:51 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: Dave Mack <csu@alembic.ACS.COM>
  10. Posting-number: Volume 20, Issue 64
  11. Archive-name: compress/part01
  12. Environment: UNIX
  13.  
  14. This is Compress, Version 4.1. This submission consists of two parts.
  15.  
  16. Modifications for version 4.1: 
  17.   o Added -r command line flag to allow recursive compression/
  18.     decompression of directory trees. As a side-effect, compress
  19.     no longer tries to compress/decompress anything that isn't
  20.     a regular file. In particular, it ignores symbolic links.
  21.   o zcat no longer cares whether a filename ends in .Z or
  22.     not - it relies on the magic number in the file. If zcat
  23.     is given a filename that doesn't end with .Z and the file
  24.     referenced doesn't exist, zcat will append a .Z and try
  25.     to open that instead.
  26.   o compress -f will now compress multiply hardlinked files.
  27.     Uncompress does not recreate the hard link, it creates
  28.     a new file.
  29.   o Removed compressdir/uncompressdir - no longer needed.
  30.   o Removed atob/btoa/tarmail/untarmail - my versions are
  31.     based on btoa 5.2 which is not compatible with the atob
  32.     included with compress4.0.
  33.   
  34. Acknowledgments:
  35.  
  36. Pat Myrto (rwing!pat@cs.washington.edu) deserves the credit
  37. for undoing all the damage I did to this version with respect
  38. to System V and for giving me the occasional kick when my
  39. changes clobbered some necessary functionality.
  40.  
  41. Thanks to James A. Woods for permitting me to corrupt his baby
  42. and for passing along some tips on ways to improve the performance
  43. over 4.0.
  44.  
  45. Thanks to the previous authors whom I didn't contact, for making
  46. the program available originally.
  47.  
  48. Dave Mack
  49. ---
  50. #! /bin/sh
  51. # This is a shell archive.  Remove anything before this line, then unpack
  52. # it by saving it into a file and typing "sh file".  To overwrite existing
  53. # files, type "sh file -c".  You can also feed this as standard input via
  54. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  55. # will see the following message at the end:
  56. #        "End of archive 1 (of 2)."
  57. # Contents:  README compress.c
  58. # Wrapped by csu@alembic on Thu May 30 16:24:07 1991
  59. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  60. if test -f 'README' -a "${1}" != "-c" ; then 
  61.   echo shar: Will not clobber existing file \"'README'\"
  62. else
  63. echo shar: Extracting \"'README'\" \(7854 characters\)
  64. sed "s/^X//" >'README' <<'END_OF_FILE'
  65. XCompress compresses files using a heavily modified version of the
  66. XLZW algorithm as described in IEEE Computer, June 1984.
  67. XSee the comments in compress.c and the Usenet article at
  68. Xthe end of this file for more details.
  69. X
  70. XThe "usermem" script attempts to determine the maximum process size.  Some
  71. Xediting of the script may be necessary (see the comments).  If you can't get
  72. Xit to work at all, just create file "USERMEM" containing the maximum process
  73. Xsize in decimal.
  74. X
  75. XThe following preprocessor symbols control the compilation of "compress.c":
  76. X
  77. X    o USERMEM        Maximum process memory on the system
  78. X    o SACREDMEM        Amount to reserve for other proceses
  79. X    o SIGNED_COMPARE_SLOW    Unsigned compare instructions are faster
  80. X    o NO_UCHAR        Don't use "unsigned char" types
  81. X    o BITS            Overrules default set by USERMEM-SACREDMEM
  82. X    o vax            Generate inline assembler
  83. X    o interdata        Defines SIGNED_COMPARE_SLOW
  84. X    o M_XENIX        Makes arrays < 65536 bytes each
  85. X    o pdp11            BITS=12, NO_UCHAR
  86. X    o z8000            BITS=12
  87. X    o pcxt            BITS=12
  88. X    o SHORTNAMES        Disallow long filenames ( > 14 characters)
  89. X    o BSD4            Call setlinebuf(stderr), lstat vs stat, etc.
  90. X    o VOIDSIG        signal returns a void pointer
  91. X    o DIRENT        use <dirent.h> instead of <sys/dir.h>
  92. X
  93. XSee the comments at the beginning of the Makefile.
  94. X
  95. XThe difference "usermem-sacredmem" determines the maximum BITS that can be
  96. Xspecified with the "-b" flag.
  97. X
  98. Xmemory: at least        BITS
  99. X------  -- -----                ----
  100. X     433,484             16
  101. X     229,600             15
  102. X     127,536             14
  103. X      73,464             13
  104. X           0             12
  105. X
  106. XThe default is BITS=16.
  107. X
  108. XThe maximum bits can be overrulled by specifying "-DBITS=bits" at
  109. Xcompilation time.
  110. X
  111. XWARNING: files compressed on a large machine with more bits than allowed by 
  112. Xa version of compress on a smaller machine cannot be decompressed!  Use the
  113. X"-b12" flag to generate a file on a large machine that can be uncompressed 
  114. Xon a 16-bit machine.
  115. X
  116. XWARNING: compatibility with compress 3.0 has not been tested in
  117. Xthe 4.1 release of compress.
  118. X
  119. XThe output of compress 4.0 is fully compatible with that of compress 3.0.
  120. XIn other words, the output of compress 4.0 may be fed into uncompress 3.0 or
  121. Xthe output of compress 3.0 may be fed into uncompress 4.0.
  122. X
  123. XThe output of compress 4.0 is not compatible with that of
  124. Xcompress 2.0.  However, compress 4.0 still accepts the output of
  125. Xcompress 2.0.  To generate output that is compatible with compress
  126. X2.0, use the undocumented "-C" flag.
  127. X
  128. XCheck the Makefile, then "make".
  129. X
  130. XSend comments, complaints and especially patches relating to
  131. Xcompress4.1 to csu@alembic.acs.com.
  132. X
  133. XRandom comments: 
  134. X
  135. Xcompress' handling of hard links has been criticized (it refuses to
  136. Xcompress a multiply linked file.) In general, this is the correct
  137. Xthing to do. Hard links cannot cross file system boundaries, and if
  138. Xthe objective of compressing files is to free disk space in a file
  139. Xsystem, compressing one link to a file won't help. Compress has no
  140. Xway of knowing where the other links are. If you REALLY want to
  141. Xcompress a hard link, use the -f flag. Be aware that when it is
  142. Xuncompressed, the hardlink will not be recreated.
  143. X
  144. Xcompress4.0's handling of symbolic links was (IMHO) incorrect.
  145. XUncompressing a collection of files should yield exactly what
  146. Xyou had before you compressed them. This didn't happen with
  147. Xsymlinks. Version 4.1 simply ignores attempts to compress
  148. Xsymbolic links, along with anything else that isn't a regular
  149. Xfile. If you're accustomed to using compress followed by tar
  150. Xto get everything that a directory references, both directly and
  151. Xindirectly, this may come as something of a disappointment.
  152. X
  153. XThe following article from James A. Woods, one of the earlier
  154. Xauthors of compress, explains its relationship to the Unisys
  155. Xpatent on the LZW compression method:
  156. X
  157. XFrom uunet!zephyr.ens.tek.com!uw-beaver!mit-eddie!wuarchive!usc!ucsd!ucbvax!agate!riacs!jaw Wed Aug  1 15:06:59 EDT 1990
  158. XArticle: 1282 of gnu.misc.discuss
  159. XPath: alembic!uunet!zephyr.ens.tek.com!uw-beaver!mit-eddie!wuarchive!usc!ucsd!ucbvax!agate!riacs!jaw
  160. XFrom: jaw@riacs.edu (James A. Woods)
  161. XNewsgroups: gnu.misc.discuss
  162. XSubject: Sperry patent #4,558,302 does *not* affect 'compress'
  163. XKeywords: data compression, algorithm, patent
  164. XMessage-ID: <1990Jul31.220935.1424@riacs.edu>
  165. XDate: 31 Jul 90 22:09:35 GMT
  166. XOrganization: RIACS, NASA Ames Research Center
  167. XLines: 69
  168. X
  169. X#  "The chief defect of Henry King
  170. X    Was chewing little bits of string."
  171. X
  172. X        -- Hilaire Belloc, Cautionary Tales [1907]
  173. X
  174. X     As a co-author of 'compress' who has had contact with an attorney for
  175. XUnisys (nee Sperry), I would like to relay a very basic admission from Unisys
  176. Xthat noncommercial use of 'compress' is perfectly legal.  'Compress' is also
  177. Xcommercially distributed by AT&T as part of Unix System 5 release 4,
  178. Xwith no further restrictions placed upon the use of the binary, as far
  179. Xas I am aware.
  180. X
  181. X     From conversations with Professor Abraham Lempel and others, it 
  182. Xappears that neither AT&T, Sun Microsystems, Hewlett Packard, nor IBM
  183. Xare paying any sort of license fees to Unisys in conjunction with patent
  184. X#4,558,302.  It may be true that some organizations are paying fees for
  185. Xdata compression technology licensed from one or more of the many holders
  186. Xof compression patents, but this is all independent from 'compress'.
  187. X
  188. X     In particular, I received a letter at NASA dated October 1, 1987 from
  189. XJohn B. Sowell of the Unisys law department, informing me for the first
  190. Xtime that some form of LZW was patented.  I naturally expressed
  191. Xskepticism that an algorithm could be patented (a murky legal area
  192. Xwhich remains so), stated that 'compress' is not identical to LZW,
  193. Xand in fact was designed, developed, and distributed before the ink
  194. Xon the patent was dry.  Several telephone conversations later, Mr. Sowell
  195. Xintimated that they would *not* seek any fees from users of 'compress'
  196. Xbut instead were signing licensees for hardware implementations of LZW.
  197. X
  198. X     So, regardless of what you believe about a shady legal area, if anyone
  199. Xfrom Unisys contacts you to extract tribute for the use of 'compress', please
  200. Xtell them that, first, it is not theirs to begin with, and, second, there is
  201. Xsomeone who will testify in court about the conversation above.
  202. XIt is not even clear if anyone can "own" 'compress', since original developer
  203. XSpencer Thomas, myself, and others placed the code in the public domain
  204. Xlong before the adoption of the Berne copyright convention.
  205. X
  206. X     In light of the events above, it seems that the Free Software
  207. XFoundation is being unduly paranoid about the use of 'compress'.
  208. XNow I can well believe that FSF is more likely to be a legal target
  209. Xthan a behemoth like AT&T, but if they are simply redistributing
  210. Xuntouched free software developed years ago in the public sector,
  211. XI see no problem.
  212. X
  213. X     Aside:  I am investigating, possibly for a case history to be
  214. Xrecycled to USENET, the particulars of data compression patents.
  215. XI am aware of the following patents: IBM's Miller-Wegman LZ variant,
  216. Xthose of Telcor and ACT [losing candidates for the British Telecom modem
  217. Xstandard], James A. Storer's work on limited lookahead as explicated in his
  218. Xtext "Data Compression (methods and theory)", Computer Science Press, 1988,
  219. Xand the various patents pending associated with the Fiala and Greene
  220. XCACM article of April, 1989 on textual substitution methods.
  221. XIf you have any lore, send it this way.
  222. X
  223. X
  224. X
  225. X                    Sincerely,
  226. X
  227. X                    James A. Woods
  228. X                    NASA Ames Research Center (RIACS)
  229. X                    jaw@riacs.edu (or ames!jaw)
  230. X
  231. X
  232. XP.S.  The algorithm patent issue certainly is a "topic A" at the moment.
  233. XOne useful reference is the review article by Anthony and Colwell --
  234. X"Litigating the Validity and Infringement of Software Patents" in
  235. XWashington and Lee Law Review, volume 41, fall 1984.  I know Robert Colwell
  236. Xpersonally.  As a practicing patent attorney, he tells me that, at a minimum,
  237. Xuse of an invention "for research purposes" is legitimate.
  238. X
  239. X
  240. X
  241. X
  242. END_OF_FILE
  243. if test 7854 -ne `wc -c <'README'`; then
  244.     echo shar: \"'README'\" unpacked with wrong size!
  245. fi
  246. # end of 'README'
  247. fi
  248. if test -f 'compress.c' -a "${1}" != "-c" ; then 
  249.   echo shar: Will not clobber existing file \"'compress.c'\"
  250. else
  251. echo shar: Extracting \"'compress.c'\" \(42620 characters\)
  252. sed "s/^X//" >'compress.c' <<'END_OF_FILE'
  253. X/* 
  254. X * Compress - data compression program 
  255. X */
  256. X#define    min(a,b)    ((a>b) ? b : a)
  257. X
  258. X/*
  259. X * machine variants which require cc -Dmachine:  pdp11, z8000, pcxt
  260. X */
  261. X
  262. X/*
  263. X * Set USERMEM to the maximum amount of physical user memory available
  264. X * in bytes.  USERMEM is used to determine the maximum BITS that can be used
  265. X * for compression.
  266. X *
  267. X * SACREDMEM is the amount of physical memory saved for others; compress
  268. X * will hog the rest.
  269. X */
  270. X#ifndef SACREDMEM
  271. X#define SACREDMEM    0
  272. X#endif
  273. X
  274. X#ifndef USERMEM
  275. X# define USERMEM     450000    /* default user memory */
  276. X#endif
  277. X
  278. X#ifdef interdata        /* (Perkin-Elmer) */
  279. X#define SIGNED_COMPARE_SLOW    /* signed compare is slower than unsigned */
  280. X#endif
  281. X
  282. X#ifdef pdp11
  283. X# define BITS     12    /* max bits/code for 16-bit machine */
  284. X# define NO_UCHAR    /* also if "unsigned char" functions as signed char */
  285. X# undef USERMEM 
  286. X#endif /* pdp11 */    /* don't forget to compile with -i */
  287. X
  288. X#ifdef z8000
  289. X# define BITS     12
  290. X# undef vax        /* weird preprocessor */
  291. X# undef USERMEM 
  292. X#endif /* z8000 */
  293. X
  294. X#ifdef pcxt
  295. X# define BITS   12
  296. X# undef USERMEM
  297. X#endif /* pcxt */
  298. X
  299. X#ifdef USERMEM
  300. X# if USERMEM >= (433484+SACREDMEM)
  301. X#  define PBITS    16
  302. X# else
  303. X#  if USERMEM >= (229600+SACREDMEM)
  304. X#   define PBITS    15
  305. X#  else
  306. X#   if USERMEM >= (127536+SACREDMEM)
  307. X#    define PBITS    14
  308. X#   else
  309. X#    if USERMEM >= (73464+SACREDMEM)
  310. X#     define PBITS    13
  311. X#    else
  312. X#     define PBITS    12
  313. X#    endif
  314. X#   endif
  315. X#  endif
  316. X# endif
  317. X# undef USERMEM
  318. X#endif /* USERMEM */
  319. X
  320. X#ifdef PBITS        /* Preferred BITS for this memory size */
  321. X# ifndef BITS
  322. X#  define BITS PBITS
  323. X# endif /* BITS */
  324. X#endif /* PBITS */
  325. X
  326. X#if BITS == 16
  327. X# define HSIZE    69001        /* 95% occupancy */
  328. X#endif
  329. X#if BITS == 15
  330. X# define HSIZE    35023        /* 94% occupancy */
  331. X#endif
  332. X#if BITS == 14
  333. X# define HSIZE    18013        /* 91% occupancy */
  334. X#endif
  335. X#if BITS == 13
  336. X# define HSIZE    9001        /* 91% occupancy */
  337. X#endif
  338. X#if BITS <= 12
  339. X# define HSIZE    5003        /* 80% occupancy */
  340. X#endif
  341. X
  342. X#ifdef M_XENIX            /* Stupid compiler can't handle arrays with */
  343. X# if BITS == 16            /* more than 65535 bytes - so we fake it */
  344. X#  define XENIX_16
  345. X# else
  346. X#  if BITS > 13            /* Code only handles BITS = 12, 13, or 16 */
  347. X#   define BITS    13
  348. X#  endif
  349. X# endif
  350. X#endif
  351. X
  352. X/*
  353. X * a code_int must be able to hold 2**BITS values of type int, and also -1
  354. X */
  355. X#if BITS > 15
  356. Xtypedef long int    code_int;
  357. X#else
  358. Xtypedef int        code_int;
  359. X#endif
  360. X
  361. X#ifdef SIGNED_COMPARE_SLOW
  362. Xtypedef unsigned long int count_int;
  363. Xtypedef unsigned short int count_short;
  364. X#else
  365. Xtypedef long int      count_int;
  366. X#endif
  367. X
  368. X#ifdef NO_UCHAR
  369. X typedef char    char_type;
  370. X#else
  371. X typedef    unsigned char    char_type;
  372. X#endif /* UCHAR */
  373. Xchar_type magic_header[] = { "\037\235" };    /* 1F 9D */
  374. X
  375. X/* Defines for third byte of header */
  376. X#define BIT_MASK    0x1f
  377. X#define BLOCK_MASK    0x80
  378. X/* Masks 0x40 and 0x20 are free.  I think 0x20 should mean that there is
  379. X   a fourth header byte (for expansion).
  380. X*/
  381. X#define INIT_BITS 9            /* initial number of bits/code */
  382. X
  383. X/*
  384. X * compress.c - File compression ala IEEE Computer, June 1984.
  385. X *
  386. X * Authors:    Spencer W. Thomas    (decvax!harpo!utah-cs!utah-gr!thomas)
  387. X *        Jim McKie        (decvax!mcvax!jim)
  388. X *        Steve Davies        (decvax!vax135!petsd!peora!srd)
  389. X *        Ken Turkowski        (decvax!decwrl!turtlevax!ken)
  390. X *        James A. Woods        (decvax!ihnp4!ames!jaw)
  391. X *        Joe Orost        (decvax!vax135!petsd!joe)
  392. X *        Dave Mack        (csu@alembic.acs.com)
  393. X *
  394. X * Revision 4.1   91/05/26        csu@alembic.acs.com
  395. X * Modified to recursively compress directories ('r' flag). As a side
  396. X * effect, compress will no longer attempt to compress things that
  397. X * aren't "regular" files. See Changes.
  398. X *
  399. X * Revision 4.0  85/07/30  12:50:00  joe
  400. X * Removed ferror() calls in output routine on every output except first.
  401. X * Prepared for release to the world.
  402. X * 
  403. X * Revision 3.6  85/07/04  01:22:21  joe
  404. X * Remove much wasted storage by overlaying hash table with the tables
  405. X * used by decompress: tab_suffix[1<<BITS], stack[8000].  Updated USERMEM
  406. X * computations.  Fixed dump_tab() DEBUG routine.
  407. X *
  408. X * Revision 3.5  85/06/30  20:47:21  jaw
  409. X * Change hash function to use exclusive-or.  Rip out hash cache.  These
  410. X * speedups render the megamemory version defunct, for now.  Make decoder
  411. X * stack global.  Parts of the RCS trunks 2.7, 2.6, and 2.1 no longer apply.
  412. X *
  413. X * Revision 3.4  85/06/27  12:00:00  ken
  414. X * Get rid of all floating-point calculations by doing all compression ratio
  415. X * calculations in fixed point.
  416. X *
  417. X * Revision 3.3  85/06/24  21:53:24  joe
  418. X * Incorporate portability suggestion for M_XENIX.  Got rid of text on #else
  419. X * and #endif lines.  Cleaned up #ifdefs for vax and interdata.
  420. X *
  421. X * Revision 3.2  85/06/06  21:53:24  jaw
  422. X * Incorporate portability suggestions for Z8000, IBM PC/XT from mailing list.
  423. X * Default to "quiet" output (no compression statistics).
  424. X *
  425. X * Revision 3.1  85/05/12  18:56:13  jaw
  426. X * Integrate decompress() stack speedups (from early pointer mods by McKie).
  427. X * Repair multi-file USERMEM gaffe.  Unify 'force' flags to mimic semantics
  428. X * of SVR2 'pack'.  Streamline block-compress table clear logic.  Increase 
  429. X * output byte count by magic number size.
  430. X * 
  431. X * Revision 3.0   84/11/27  11:50:00  petsd!joe
  432. X * Set HSIZE depending on BITS.  Set BITS depending on USERMEM.  Unrolled
  433. X * loops in clear routines.  Added "-C" flag for 2.0 compatibility.  Used
  434. X * unsigned compares on Perkin-Elmer.  Fixed foreground check.
  435. X *
  436. X * Revision 2.7   84/11/16  19:35:39  ames!jaw
  437. X * Cache common hash codes based on input statistics; this improves
  438. X * performance for low-density raster images.  Pass on #ifdef bundle
  439. X * from Turkowski.
  440. X *
  441. X * Revision 2.6   84/11/05  19:18:21  ames!jaw
  442. X * Vary size of hash tables to reduce time for small files.
  443. X * Tune PDP-11 hash function.
  444. X *
  445. X * Revision 2.5   84/10/30  20:15:14  ames!jaw
  446. X * Junk chaining; replace with the simpler (and, on the VAX, faster)
  447. X * double hashing, discussed within.  Make block compression standard.
  448. X *
  449. X * Revision 2.4   84/10/16  11:11:11  ames!jaw
  450. X * Introduce adaptive reset for block compression, to boost the rate
  451. X * another several percent.  (See mailing list notes.)
  452. X *
  453. X * Revision 2.3   84/09/22  22:00:00  petsd!joe
  454. X * Implemented "-B" block compress.  Implemented REVERSE sorting of tab_next.
  455. X * Bug fix for last bits.  Changed fwrite to putchar loop everywhere.
  456. X *
  457. X * Revision 2.2   84/09/18  14:12:21  ames!jaw
  458. X * Fold in news changes, small machine typedef from thomas,
  459. X * #ifdef interdata from joe.
  460. X *
  461. X * Revision 2.1   84/09/10  12:34:56  ames!jaw
  462. X * Configured fast table lookup for 32-bit machines.
  463. X * This cuts user time in half for b <= FBITS, and is useful for news batching
  464. X * from VAX to PDP sites.  Also sped up decompress() [fwrite->putc] and
  465. X * added signal catcher [plus beef in writeerr()] to delete effluvia.
  466. X *
  467. X * Revision 2.0   84/08/28  22:00:00  petsd!joe
  468. X * Add check for foreground before prompting user.  Insert maxbits into
  469. X * compressed file.  Force file being uncompressed to end with ".Z".
  470. X * Added "-c" flag and "zcat".  Prepared for release.
  471. X *
  472. X * Revision 1.10  84/08/24  18:28:00  turtlevax!ken
  473. X * Will only compress regular files (no directories), added a magic number
  474. X * header (plus an undocumented -n flag to handle old files without headers),
  475. X * added -f flag to force overwriting of possibly existing destination file,
  476. X * otherwise the user is prompted for a response.  Will tack on a .Z to a
  477. X * filename if it doesn't have one when decompressing.  Will only replace
  478. X * file if it was compressed.
  479. X *
  480. X * Revision 1.9  84/08/16  17:28:00  turtlevax!ken
  481. X * Removed scanargs(), getopt(), added .Z extension and unlimited number of
  482. X * filenames to compress.  Flags may be clustered (-Ddvb12) or separated
  483. X * (-D -d -v -b 12), or combination thereof.  Modes and other status is
  484. X * copied with copystat().  -O bug for 4.2 seems to have disappeared with
  485. X * 1.8.
  486. X *
  487. X * Revision 1.8  84/08/09  23:15:00  joe
  488. X * Made it compatible with vax version, installed jim's fixes/enhancements
  489. X *
  490. X * Revision 1.6  84/08/01  22:08:00  joe
  491. X * Sped up algorithm significantly by sorting the compress chain.
  492. X *
  493. X * Revision 1.5  84/07/13  13:11:00  srd
  494. X * Added C version of vax asm routines.  Changed structure to arrays to
  495. X * save much memory.  Do unsigned compares where possible (faster on
  496. X * Perkin-Elmer)
  497. X *
  498. X * Revision 1.4  84/07/05  03:11:11  thomas
  499. X * Clean up the code a little and lint it.  (Lint complains about all
  500. X * the regs used in the asm, but I'm not going to "fix" this.)
  501. X *
  502. X * Revision 1.3  84/07/05  02:06:54  thomas
  503. X * Minor fixes.
  504. X *
  505. X * Revision 1.2  84/07/05  00:27:27  thomas
  506. X * Add variable bit length output.
  507. X *
  508. X */
  509. Xstatic char version_id[] = "compress.c 4.1";
  510. X
  511. X#include <stdio.h>
  512. X#include <ctype.h>
  513. X#include <signal.h>
  514. X#include <sys/types.h>
  515. X#include <sys/stat.h>
  516. X#ifndef DIRENT
  517. X#include <sys/dir.h>
  518. X#else
  519. X#include <dirent.h>
  520. X#endif
  521. X#include <errno.h>
  522. Xextern int errno;
  523. X
  524. X#include "patchlevel.h"
  525. X
  526. X#define ARGVAL() (*++(*argv) || (--argc && *++argv))
  527. X
  528. Xint n_bits;                /* number of bits/code */
  529. Xint maxbits = BITS;            /* user settable max # bits/code */
  530. Xcode_int maxcode;            /* maximum code, given n_bits */
  531. Xcode_int maxmaxcode = 1 << BITS;    /* should NEVER generate this code */
  532. X#ifdef COMPATIBLE        /* But wrong! */
  533. X# define MAXCODE(n_bits)    (1 << (n_bits) - 1)
  534. X#else
  535. X# define MAXCODE(n_bits)    ((1 << (n_bits)) - 1)
  536. X#endif /* COMPATIBLE */
  537. X
  538. X#ifdef XENIX_16
  539. Xcount_int htab0[8192];
  540. Xcount_int htab1[8192];
  541. Xcount_int htab2[8192];
  542. Xcount_int htab3[8192];
  543. Xcount_int htab4[8192];
  544. Xcount_int htab5[8192];
  545. Xcount_int htab6[8192];
  546. Xcount_int htab7[8192];
  547. Xcount_int htab8[HSIZE-65536];
  548. Xcount_int * htab[9] = {
  549. X    htab0, htab1, htab2, htab3, htab4, htab5, htab6, htab7, htab8 };
  550. X
  551. X#define htabof(i)    (htab[(i) >> 13][(i) & 0x1fff])
  552. Xunsigned short code0tab[16384];
  553. Xunsigned short code1tab[16384];
  554. Xunsigned short code2tab[16384];
  555. Xunsigned short code3tab[16384];
  556. Xunsigned short code4tab[16384];
  557. Xunsigned short * codetab[5] = {
  558. X    code0tab, code1tab, code2tab, code3tab, code4tab };
  559. X
  560. X#define codetabof(i)    (codetab[(i) >> 14][(i) & 0x3fff])
  561. X
  562. X#else    /* Normal machine */
  563. Xcount_int htab [HSIZE];
  564. Xunsigned short codetab [HSIZE];
  565. X#define htabof(i)    htab[i]
  566. X#define codetabof(i)    codetab[i]
  567. X#endif    /* XENIX_16 */
  568. Xcode_int hsize = HSIZE;            /* for dynamic table sizing */
  569. Xcount_int fsize;
  570. X
  571. X/*
  572. X * To save much memory, we overlay the table used by compress() with those
  573. X * used by decompress().  The tab_prefix table is the same size and type
  574. X * as the codetab.  The tab_suffix table needs 2**BITS characters.  We
  575. X * get this from the beginning of htab.  The output stack uses the rest
  576. X * of htab, and contains characters.  There is plenty of room for any
  577. X * possible stack (stack used to be 8000 characters).
  578. X */
  579. X
  580. X#define tab_prefixof(i)    codetabof(i)
  581. X#ifdef XENIX_16
  582. X# define tab_suffixof(i)    ((char_type *)htab[(i)>>15])[(i) & 0x7fff]
  583. X# define de_stack        ((char_type *)(htab2))
  584. X#else    /* Normal machine */
  585. X# define tab_suffixof(i)    ((char_type *)(htab))[i]
  586. X# define de_stack        ((char_type *)&tab_suffixof(1<<BITS))
  587. X#endif    /* XENIX_16 */
  588. X
  589. Xcode_int free_ent = 0;            /* first unused entry */
  590. Xint exit_stat = 0;
  591. X
  592. Xcode_int getcode();
  593. X
  594. XUsage() {
  595. X#ifdef DEBUG
  596. Xfprintf(stderr,"Usage: compress [-dDVfcr] [-b maxbits] [file ...]\n");
  597. X}
  598. Xint debug = 0;
  599. X#else
  600. Xfprintf(stderr,"Usage: compress [-dfvcVr] [-b maxbits] [file ...]\n");
  601. X}
  602. X#endif /* DEBUG */
  603. Xint nomagic = 0;    /* Use a 3-byte magic number header, unless old file */
  604. Xint zcat_flg = 0;    /* Write output on stdout, suppress messages */
  605. Xint quiet = 1;        /* don't tell me about compression */
  606. X
  607. X/*
  608. X * block compression parameters -- after all codes are used up,
  609. X * and compression rate changes, start over.
  610. X */
  611. Xint block_compress = BLOCK_MASK;
  612. Xint clear_flg = 0;
  613. Xlong int ratio = 0;
  614. X#if BITS == 16
  615. X#define CHECK_GAP 50000    /* ratio check interval recommended by jaw */
  616. X#else
  617. X#define CHECK_GAP 10000    /* ratio check interval */
  618. X#endif
  619. Xcount_int checkpoint = CHECK_GAP;
  620. X/*
  621. X * the next two codes should not be changed lightly, as they must not
  622. X * lie within the contiguous general code space.
  623. X */ 
  624. X#define FIRST    257    /* first free entry */
  625. X#define    CLEAR    256    /* table clear output code */
  626. X
  627. Xint force = 0;
  628. Xchar ofname [100];
  629. X#ifdef DEBUG
  630. Xint verbose = 0;
  631. X#endif /* DEBUG */
  632. X
  633. X#ifndef    VOIDSIG
  634. Xint (*bgnd_flag)();
  635. X#else
  636. Xvoid (*bgnd_flag)();
  637. X#endif    /* VOIDSIG */
  638. X
  639. X
  640. Xint do_decomp = 0;
  641. X
  642. X/*****************************************************************
  643. X * TAG( main )
  644. X *
  645. X * Algorithm from "A Technique for High Performance Data Compression",
  646. X * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
  647. X *
  648. X * Usage: compress [-dfvc] [-b bits] [file ...]
  649. X * Inputs:
  650. X *    -d:        If given, decompression is done instead.
  651. X *
  652. X *      -c:         Write output on stdout, don't remove original.
  653. X *
  654. X *      -b:         Parameter limits the max number of bits/code.
  655. X *
  656. X *    -f:        Forces output file to be generated, even if one already
  657. X *            exists, and even if no space is saved by compressing.
  658. X *            If -f is not used, the user will be prompted if stdin is
  659. X *            a tty, otherwise, the output file will not be overwritten.
  660. X *
  661. X *      -v:        Write compression statistics
  662. X *
  663. X *    -r:        Recursive. If a filename is a directory, descend
  664. X *            into it and compress everything in it.
  665. X *
  666. X *     file ...:   Files to be compressed.  If none specified, stdin
  667. X *            is used.
  668. X * Outputs:
  669. X *    file.Z:        Compressed form of file with same mode, owner, and utimes
  670. X *     or stdout   (if stdin used as input)
  671. X *
  672. X * Assumptions:
  673. X *    When filenames are given, replaces with the compressed version
  674. X *    (.Z suffix) only if the file decreases in size.
  675. X * Algorithm:
  676. X *     Modified Lempel-Ziv method (LZW).  Basically finds common
  677. X * substrings and replaces them with a variable size code.  This is
  678. X * deterministic, and can be done on the fly.  Thus, the decompression
  679. X * procedure needs no input table, but tracks the way the table was built.
  680. X */
  681. X
  682. Xint overwrite = 0;    /* Do not overwrite unless given -f flag */
  683. Xint recursive = 0;  /* compress directories */
  684. Xmain( argc, argv )
  685. Xregister int argc; char **argv;
  686. X{
  687. X    char **filelist, **fileptr;
  688. X    char *cp, *rindex(), *malloc();
  689. X    extern onintr(), oops();
  690. X
  691. X
  692. X    if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) {
  693. X    signal ( SIGINT, onintr );
  694. X    signal ( SIGSEGV, oops );
  695. X    }
  696. X
  697. X#ifdef COMPATIBLE
  698. X    nomagic = 1;    /* Original didn't have a magic number */
  699. X#endif /* COMPATIBLE */
  700. X
  701. X    filelist = fileptr = (char **)(malloc(argc * sizeof(*argv)));
  702. X    *filelist = NULL;
  703. X
  704. X    if((cp = rindex(argv[0], '/')) != 0) {
  705. X    cp++;
  706. X    } else {
  707. X    cp = argv[0];
  708. X    }
  709. X    if(strcmp(cp, "uncompress") == 0) {
  710. X    do_decomp = 1;
  711. X    } else if(strcmp(cp, "zcat") == 0) {
  712. X    do_decomp = 1;
  713. X    zcat_flg = 1;
  714. X    }
  715. X
  716. X#ifdef BSD4
  717. X    /* 4.2BSD dependent - take it out if not */
  718. X    setlinebuf( stderr );
  719. X#endif /* BSD4 */
  720. X
  721. X    /* Argument Processing
  722. X     * All flags are optional.
  723. X     * -D => debug
  724. X     * -V => print Version; debug verbose
  725. X     * -d => do_decomp
  726. X     * -v => unquiet
  727. X     * -f => force overwrite of output file
  728. X     * -n => no header: useful to uncompress old files
  729. X     * -b maxbits => maxbits.  If -b is specified, then maxbits MUST be
  730. X     *        given also.
  731. X     * -c => cat all output to stdout
  732. X     * -C => generate output compatible with compress 2.0.
  733. X     * -r => recursively compress directories
  734. X     * if a string is left, must be an input filename.
  735. X     */
  736. X    for (argc--, argv++; argc > 0; argc--, argv++) {
  737. X    if (**argv == '-') {    /* A flag argument */
  738. X        while (*++(*argv)) {    /* Process all flags in this arg */
  739. X        switch (**argv) {
  740. X#ifdef DEBUG
  741. X            case 'D':
  742. X            debug = 1;
  743. X            break;
  744. X            case 'V':
  745. X            verbose = 1;
  746. X            version();
  747. X            break;
  748. X#else
  749. X            case 'V':
  750. X            version();
  751. X            break;
  752. X#endif /* DEBUG */
  753. X            case 'v':
  754. X            quiet = 0;
  755. X            break;
  756. X            case 'd':
  757. X            do_decomp = 1;
  758. X            break;
  759. X            case 'f':
  760. X            case 'F':
  761. X            overwrite = 1;
  762. X            force = 1;
  763. X            break;
  764. X            case 'n':
  765. X            nomagic = 1;
  766. X            break;
  767. X            case 'C':
  768. X            block_compress = 0;
  769. X            break;
  770. X            case 'b':
  771. X            if (!ARGVAL()) {
  772. X                fprintf(stderr, "Missing maxbits\n");
  773. X                Usage();
  774. X                exit(1);
  775. X            }
  776. X            maxbits = atoi(*argv);
  777. X            goto nextarg;
  778. X            case 'c':
  779. X            zcat_flg = 1;
  780. X            break;
  781. X            case 'q':
  782. X            quiet = 1;
  783. X            break;
  784. X            case 'r':
  785. X            case 'R':
  786. X            recursive = 1;
  787. X            break;
  788. X            default:
  789. X            fprintf(stderr, "Unknown flag: '%c'; ", **argv);
  790. X            Usage();
  791. X            exit(1);
  792. X        }
  793. X        }
  794. X    }
  795. X    else {        /* Input file name */
  796. X        *fileptr++ = *argv;    /* Build input file list */
  797. X        *fileptr = NULL;
  798. X        /* process nextarg; */
  799. X    }
  800. X    nextarg: continue;
  801. X    }
  802. X
  803. X    if(maxbits < INIT_BITS) maxbits = INIT_BITS;
  804. X    if (maxbits > BITS) maxbits = BITS;
  805. X    maxmaxcode = 1 << maxbits;
  806. X
  807. X    if (*filelist != NULL) {
  808. X      for (fileptr = filelist; *fileptr; fileptr++) {
  809. X    comprexx(fileptr);
  810. X      }
  811. X    } else {        /* Standard input */
  812. X    if (do_decomp == 0) {
  813. X        compress();
  814. X        if(!quiet)
  815. X            putc('\n', stderr);
  816. X    } else {
  817. X        /* Check the magic number */
  818. X        if (nomagic == 0) {
  819. X        if ((getchar()!=(magic_header[0] & 0xFF))
  820. X         || (getchar()!=(magic_header[1] & 0xFF))) {
  821. X            fprintf(stderr, "stdin: not in compressed format\n");
  822. X            exit(1);
  823. X        }
  824. X        maxbits = getchar();    /* set -b from file */
  825. X        block_compress = maxbits & BLOCK_MASK;
  826. X        maxbits &= BIT_MASK;
  827. X        maxmaxcode = 1 << maxbits;
  828. X        fsize = 100000;        /* assume stdin large for USERMEM */
  829. X        if(maxbits > BITS) {
  830. X            fprintf(stderr,
  831. X            "stdin: compressed with %d bits, can only handle %d bits\n",
  832. X            maxbits, BITS);
  833. X            exit(1);
  834. X        }
  835. X        }
  836. X#ifndef DEBUG
  837. X        decompress();
  838. X#else   /* DEBUG */
  839. X        if (debug == 0)    decompress();
  840. X        else        printcodes();
  841. X        if (verbose)    dump_tab();
  842. X#endif /* DEBUG */
  843. X    }
  844. X    }
  845. X    exit(exit_stat);
  846. X}
  847. X
  848. Xcomprexx(fileptr)
  849. Xchar **fileptr;
  850. X{
  851. X    struct stat statbuf,insbuf;
  852. X    char tempname[1024], *cp;
  853. X
  854. X    strcpy(tempname,*fileptr);
  855. X    errno = 0;
  856. X#ifdef    BSD4
  857. X    if (lstat(tempname,&insbuf) == -1) {
  858. X#else
  859. X    if (stat(tempname,&insbuf) == -1) {
  860. X#endif
  861. X      if ( do_decomp ) {
  862. X        switch (errno) {
  863. X        case ENOENT:    /* file doesn't exist */
  864. X          /*
  865. X          ** if the given name doesn't end with .Z, try appending one
  866. X          ** This is obviously the wrong thing to do if it's a 
  867. X          ** directory, but it shouldn't do any harm.
  868. X          */
  869. X          if (strcmp(tempname + strlen(tempname) - 2, ".Z") != 0) {
  870. X        strcat(tempname,".Z");
  871. X        errno = 0;
  872. X#ifdef    BSD4
  873. X        if (lstat(tempname,&insbuf) == -1) {
  874. X#else
  875. X        if (stat(tempname,&insbuf) == -1) {
  876. X#endif
  877. X          perror(tempname);
  878. X          return;
  879. X        }
  880. X          }
  881. X          else {
  882. X        perror(tempname);
  883. X        return;
  884. X          }
  885. X          break;
  886. X        default:
  887. X          perror(tempname);
  888. X          return;
  889. X        } /* end switch */
  890. X      } /* endif */
  891. X      else {
  892. X        /* we can't stat the file, ignore it */
  893. X          perror(tempname);
  894. X          return;
  895. X      }
  896. X    } /* endif */
  897. X
  898. X    switch (insbuf.st_mode & S_IFMT) {
  899. X    case S_IFDIR:    /* directory */
  900. X      if (recursive)
  901. X        compdir(tempname);
  902. X      break;
  903. X
  904. X    case S_IFREG:    /* regular file */
  905. X      exit_stat = 0;
  906. X      if (do_decomp != 0) {
  907. X    /* DECOMPRESSION */
  908. X        if ( ! zcat_flg ) {
  909. X          if (strcmp(tempname + strlen(tempname) - 2, ".Z") != 0) {
  910. X        if ( ! quiet ) {
  911. X          fprintf(stderr,"%s - no .Z suffix\n",tempname);
  912. X        }
  913. X        return;
  914. X          }
  915. X        }
  916. X        /* Open input file */
  917. X        if ((freopen(tempname, "r", stdin)) == NULL) {
  918. X          perror(tempname); return;
  919. X        }
  920. X        /* Check the magic number */
  921. X        if (nomagic == 0) {
  922. X            if ((getchar() != (magic_header[0] & 0xFF))
  923. X             || (getchar() != (magic_header[1] & 0xFF))) {
  924. X            fprintf(stderr, "%s: not in compressed format\n",
  925. X                tempname);
  926. X                    return;
  927. X            }
  928. X            maxbits = getchar();    /* set -b from file */
  929. X            block_compress = maxbits & BLOCK_MASK;
  930. X            maxbits &= BIT_MASK;
  931. X            maxmaxcode = 1 << maxbits;
  932. X            if(maxbits > BITS) {
  933. X            fprintf(stderr,
  934. X            "%s: compressed with %d bits, can only handle %d bits\n",
  935. X            tempname, maxbits, BITS);
  936. X                    return;
  937. X            }
  938. X        }
  939. X            /* we have to ignore SIGINT for a while, otherwise
  940. X           a ^C can nuke an existing file with ofname */
  941. X            signal(SIGINT,SIG_IGN);
  942. X        /* Generate output filename */
  943. X        strcpy(ofname, tempname);
  944. X        /* Check for .Z suffix */
  945. X        if (strcmp(tempname + strlen(tempname) - 2, ".Z") == 0) {
  946. X          ofname[strlen(tempname) - 2] = '\0';  /* Strip off .Z */
  947. X        }
  948. X        }
  949. X        else {
  950. X    /* COMPRESSION */
  951. X        if (strcmp(tempname + strlen(tempname) - 2, ".Z") == 0) {
  952. X                fprintf(stderr, "%s: already has .Z suffix -- no change\n",
  953. X                tempname);
  954. X            return;
  955. X        }
  956. X        /* Open input file */
  957. X        if ((freopen(tempname, "r", stdin)) == NULL) {
  958. X            perror(tempname); return;
  959. X        }
  960. X        fsize = (long) insbuf.st_size;
  961. X        /*
  962. X         * tune hash table size for small files -- ad hoc,
  963. X         * but the sizes match earlier #defines, which
  964. X         * serve as upper bounds on the number of output codes. 
  965. X         */
  966. X        hsize = HSIZE;
  967. X        if ( fsize < (1 << 12) )
  968. X            hsize = min ( 5003, HSIZE );
  969. X        else if ( fsize < (1 << 13) )
  970. X            hsize = min ( 9001, HSIZE );
  971. X        else if ( fsize < (1 << 14) )
  972. X            hsize = min ( 18013, HSIZE );
  973. X        else if ( fsize < (1 << 15) )
  974. X            hsize = min ( 35023, HSIZE );
  975. X        else if ( fsize < 47000 )
  976. X            hsize = min ( 50021, HSIZE );
  977. X
  978. X            /* we have to ignore SIGINT for a while, otherwise
  979. X           a ^C can nuke an existing file with ofname */
  980. X            signal(SIGINT,SIG_IGN);
  981. X        /* Generate output filename */
  982. X        strcpy(ofname, tempname);
  983. X#ifdef SHORTNAMES    /* Short filenames */
  984. X        if ((cp=rindex(ofname,'/')) != NULL)    cp++;
  985. X        else                    cp = ofname;
  986. X        if (strlen(cp) > 12) {
  987. X            fprintf(stderr,"%s: filename too long to tack on .Z\n",cp);
  988. X            signal(SIGINT,onintr);
  989. X            return;
  990. X        }
  991. X#endif  /* SHORTNAMES */
  992. X        strcat(ofname, ".Z");
  993. X        }
  994. X        /* Check for overwrite of existing file */
  995. X        if (overwrite == 0 && zcat_flg == 0) {
  996. X        if (stat(ofname, &statbuf) == 0) {
  997. X            char response[2];
  998. X            response[0] = 'n';
  999. X            fprintf(stderr, "%s already exists;", ofname);
  1000. X            if (foreground()) {
  1001. X            fprintf(stderr, " do you wish to overwrite %s (y or n)? ",
  1002. X            ofname);
  1003. X            fflush(stderr);
  1004. X            read(2, response, 2);
  1005. X            while (response[1] != '\n') {
  1006. X                if (read(2, response+1, 1) < 0) {    /* Ack! */
  1007. X                perror("stderr"); break;
  1008. X                }
  1009. X            }
  1010. X            }
  1011. X            if (response[0] != 'y') {
  1012. X            fprintf(stderr, "\tnot overwritten\n");
  1013. X            signal(SIGINT,onintr);
  1014. X            return;
  1015. X            }
  1016. X        }
  1017. X        }
  1018. X        signal(SIGINT,onintr);
  1019. X        if(zcat_flg == 0) {        /* Open output file */
  1020. X        if (freopen(ofname, "w", stdout) == NULL) {
  1021. X            perror(ofname);
  1022. X            return;
  1023. X        }
  1024. X        if(!quiet)
  1025. X            fprintf(stderr, "%s: ", tempname);
  1026. X        }
  1027. X
  1028. X        /* Actually do the compression/decompression */
  1029. X        if (do_decomp == 0)    compress();
  1030. X#ifndef DEBUG
  1031. X        else            decompress();
  1032. X#else
  1033. X        else if (debug == 0)    decompress();
  1034. X        else            printcodes();
  1035. X        if (verbose)        dump_tab();
  1036. X#endif /* DEBUG */
  1037. X        if(zcat_flg == 0) {
  1038. X        copystat(tempname, ofname);    /* Copy stats */
  1039. X        if((exit_stat == 1) || (!quiet))
  1040. X            putc('\n', stderr);
  1041. X        }
  1042. X    default:
  1043. X        break;
  1044. X    } /* end switch */
  1045. X    return;
  1046. X} /* end comprexx */
  1047. X
  1048. Xcompdir(dir)
  1049. Xchar *dir;
  1050. X{
  1051. X    DIR *dirp;
  1052. X#ifndef    DIRENT
  1053. X    register struct direct *dp;
  1054. X#else
  1055. X    register struct dirent *dp;
  1056. X#endif
  1057. X    char nbuf[1024];
  1058. X    char *nptr = nbuf;
  1059. X    dirp = opendir(dir);
  1060. X    if (dirp == NULL) {
  1061. X        printf("%s unreadable\n", dir);        /* not stderr! */
  1062. X        return ;
  1063. X    }
  1064. X    while (dp = readdir(dirp)) {
  1065. X        if (dp->d_ino == 0)
  1066. X            continue;
  1067. X        if (strcmp(dp->d_name,".") == 0 || strcmp(dp->d_name,"..") == 0)
  1068. X            continue;
  1069. X        strcpy(nbuf,dir);
  1070. X        strcat(nbuf,"/");
  1071. X        strcat(nbuf,dp->d_name);
  1072. X        comprexx(&nptr);
  1073. X      }
  1074. X    closedir(dirp);
  1075. X    return;
  1076. X} /* end compdir */
  1077. X
  1078. Xstatic int offset;
  1079. Xlong int in_count = 1;            /* length of input */
  1080. Xlong int bytes_out;            /* length of compressed output */
  1081. Xlong int out_count = 0;            /* # of codes output (for debugging) */
  1082. X
  1083. X/*
  1084. X * compress stdin to stdout
  1085. X *
  1086. X * Algorithm:  use open addressing double hashing (no chaining) on the 
  1087. X * prefix code / next character combination.  We do a variant of Knuth's
  1088. X * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  1089. X * secondary probe.  Here, the modular division first probe is gives way
  1090. X * to a faster exclusive-or manipulation.  Also do block compression with
  1091. X * an adaptive reset, whereby the code table is cleared when the compression
  1092. X * ratio decreases, but after the table fills.  The variable-length output
  1093. X * codes are re-sized at this point, and a special CLEAR code is generated
  1094. X * for the decompressor.  Late addition:  construct the table according to
  1095. X * file size for noticeable speed improvement on small files.  Please direct
  1096. X * questions about this implementation to ames!jaw.
  1097. X */
  1098. X
  1099. Xcompress() {
  1100. X    register long fcode;
  1101. X    register code_int i = 0;
  1102. X    register int c;
  1103. X    register code_int ent;
  1104. X#ifdef XENIX_16
  1105. X    register code_int disp;
  1106. X#else    /* Normal machine */
  1107. X    register int disp;
  1108. X#endif
  1109. X    register code_int hsize_reg;
  1110. X    register int hshift;
  1111. X
  1112. X#ifndef COMPATIBLE
  1113. X    if (nomagic == 0) {
  1114. X    putchar(magic_header[0]); putchar(magic_header[1]);
  1115. X    putchar((char)(maxbits | block_compress));
  1116. X    if(ferror(stdout))
  1117. X        writeerr();
  1118. X    }
  1119. X#endif /* COMPATIBLE */
  1120. X
  1121. X    offset = 0;
  1122. X    bytes_out = 3;        /* includes 3-byte header mojo */
  1123. X    out_count = 0;
  1124. X    clear_flg = 0;
  1125. X    ratio = 0;
  1126. X    in_count = 1;
  1127. X    checkpoint = CHECK_GAP;
  1128. X    maxcode = MAXCODE(n_bits = INIT_BITS);
  1129. X    free_ent = ((block_compress) ? FIRST : 256 );
  1130. X
  1131. X    ent = getchar ();
  1132. X
  1133. X    hshift = 0;
  1134. X    for ( fcode = (long) hsize;  fcode < 65536L; fcode *= 2L )
  1135. X        hshift++;
  1136. X    hshift = 8 - hshift;        /* set hash code range bound */
  1137. X
  1138. X    hsize_reg = hsize;
  1139. X    cl_hash( (count_int) hsize_reg);        /* clear hash table */
  1140. X
  1141. X#ifdef SIGNED_COMPARE_SLOW
  1142. X    while ( (c = getchar()) != (unsigned) EOF ) {
  1143. X#else
  1144. X    while ( (c = getchar()) != EOF ) {
  1145. X#endif
  1146. X    in_count++;
  1147. X    fcode = (long) (((long) c << maxbits) + ent);
  1148. X     i = ((c << hshift) ^ ent);    /* xor hashing */
  1149. X
  1150. X    if ( htabof (i) == fcode ) {
  1151. X        ent = codetabof (i);
  1152. X        continue;
  1153. X    } else if ( (long)htabof (i) < 0 )    /* empty slot */
  1154. X        goto nomatch;
  1155. X     disp = hsize_reg - i;        /* secondary hash (after G. Knott) */
  1156. X    if ( i == 0 )
  1157. X        disp = 1;
  1158. Xprobe:
  1159. X    if ( (i -= disp) < 0 )
  1160. X        i += hsize_reg;
  1161. X
  1162. X    if ( htabof (i) == fcode ) {
  1163. X        ent = codetabof (i);
  1164. X        continue;
  1165. X    }
  1166. X    if ( (long)htabof (i) > 0 ) 
  1167. X        goto probe;
  1168. Xnomatch:
  1169. X    output ( (code_int) ent );
  1170. X    out_count++;
  1171. X     ent = c;
  1172. X#ifdef SIGNED_COMPARE_SLOW
  1173. X    if ( (unsigned) free_ent < (unsigned) maxmaxcode) {
  1174. X#else
  1175. X    if ( free_ent < maxmaxcode ) {
  1176. X#endif
  1177. X         codetabof (i) = free_ent++;    /* code -> hashtable */
  1178. X        htabof (i) = fcode;
  1179. X    }
  1180. X    else if ( (count_int)in_count >= checkpoint && block_compress )
  1181. X        cl_block ();
  1182. X    }
  1183. X    /*
  1184. X     * Put out the final code.
  1185. X     */
  1186. X    output( (code_int)ent );
  1187. X    out_count++;
  1188. X    output( (code_int)-1 );
  1189. X
  1190. X    /*
  1191. X     * Print out stats on stderr
  1192. X     */
  1193. X    if(zcat_flg == 0 && !quiet) {
  1194. X#ifdef DEBUG
  1195. X    fprintf( stderr,
  1196. X        "%ld chars in, %ld codes (%ld bytes) out, compression factor: ",
  1197. X        in_count, out_count, bytes_out );
  1198. X    prratio( stderr, in_count, bytes_out );
  1199. X    fprintf( stderr, "\n");
  1200. X    fprintf( stderr, "\tCompression as in compact: " );
  1201. X    prratio( stderr, in_count-bytes_out, in_count );
  1202. X    fprintf( stderr, "\n");
  1203. X    fprintf( stderr, "\tLargest code (of last block) was %d (%d bits)\n",
  1204. X        free_ent - 1, n_bits );
  1205. X#else /* !DEBUG */
  1206. X    fprintf( stderr, "Compression: " );
  1207. X    prratio( stderr, in_count-bytes_out, in_count );
  1208. X#endif /* DEBUG */
  1209. X    }
  1210. X    if(bytes_out > in_count)    /* exit(2) if no savings */
  1211. X    exit_stat = 2;
  1212. X    return;
  1213. X}
  1214. X
  1215. X/*****************************************************************
  1216. X * TAG( output )
  1217. X *
  1218. X * Output the given code.
  1219. X * Inputs:
  1220. X *     code:    A n_bits-bit integer.  If == -1, then EOF.  This assumes
  1221. X *        that n_bits =< (long)wordsize - 1.
  1222. X * Outputs:
  1223. X *     Outputs code to the file.
  1224. X * Assumptions:
  1225. X *    Chars are 8 bits long.
  1226. X * Algorithm:
  1227. X *     Maintain a BITS character long buffer (so that 8 codes will
  1228. X * fit in it exactly).  Use the VAX insv instruction to insert each
  1229. X * code in turn.  When the buffer fills up empty it and start over.
  1230. X */
  1231. X
  1232. Xstatic char buf[BITS];
  1233. X
  1234. X#ifndef vax
  1235. Xchar_type lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
  1236. Xchar_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
  1237. X#endif /* vax */
  1238. X
  1239. Xoutput( code )
  1240. Xcode_int  code;
  1241. X{
  1242. X#ifdef DEBUG
  1243. X    static int col = 0;
  1244. X#endif /* DEBUG */
  1245. X
  1246. X    /*
  1247. X     * On the VAX, it is important to have the register declarations
  1248. X     * in exactly the order given, or the asm will break.
  1249. X     */
  1250. X    register int r_off = offset, bits= n_bits;
  1251. X    register char * bp = buf;
  1252. X
  1253. X#ifdef DEBUG
  1254. X    if ( verbose )
  1255. X        fprintf( stderr, "%5d%c", code,
  1256. X            (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
  1257. X#endif /* DEBUG */
  1258. X    if ( code >= 0 ) {
  1259. X#ifdef vax
  1260. X    /* VAX DEPENDENT!! Implementation on other machines is below.
  1261. X     *
  1262. X     * Translation: Insert BITS bits from the argument starting at
  1263. X     * offset bits from the beginning of buf.
  1264. X     */
  1265. X    0;    /* Work around for pcc -O bug with asm and if stmt */
  1266. X    asm( "insv    4(ap),r11,r10,(r9)" );
  1267. X#else /* not a vax */
  1268. X/* 
  1269. X * byte/bit numbering on the VAX is simulated by the following code
  1270. X */
  1271. X    /*
  1272. X     * Get to the first byte.
  1273. X     */
  1274. X    bp += (r_off >> 3);
  1275. X    r_off &= 7;
  1276. X    /*
  1277. X     * Since code is always >= 8 bits, only need to mask the first
  1278. X     * hunk on the left.
  1279. X     */
  1280. X    *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
  1281. X    bp++;
  1282. X    bits -= (8 - r_off);
  1283. X    code >>= 8 - r_off;
  1284. X    /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  1285. X    if ( bits >= 8 ) {
  1286. X        *bp++ = code;
  1287. X        code >>= 8;
  1288. X        bits -= 8;
  1289. X    }
  1290. X    /* Last bits. */
  1291. X    if(bits)
  1292. X        *bp = code;
  1293. X#endif /* vax */
  1294. X    offset += n_bits;
  1295. X    if ( offset == (n_bits << 3) ) {
  1296. X        bp = buf;
  1297. X        bits = n_bits;
  1298. X        bytes_out += bits;
  1299. X        do
  1300. X        putchar(*bp++);
  1301. X        while(--bits);
  1302. X        offset = 0;
  1303. X    }
  1304. X
  1305. X    /*
  1306. X     * If the next entry is going to be too big for the code size,
  1307. X     * then increase it, if possible.
  1308. X     */
  1309. X    if ( free_ent > maxcode || (clear_flg > 0))
  1310. X    {
  1311. X        /*
  1312. X         * Write the whole buffer, because the input side won't
  1313. X         * discover the size increase until after it has read it.
  1314. X         */
  1315. X        if ( offset > 0 ) {
  1316. X        if( fwrite( buf, 1, n_bits, stdout ) != n_bits)
  1317. X            writeerr();
  1318. X        bytes_out += n_bits;
  1319. X        }
  1320. X        offset = 0;
  1321. X
  1322. X        if ( clear_flg ) {
  1323. X                maxcode = MAXCODE (n_bits = INIT_BITS);
  1324. X            clear_flg = 0;
  1325. X        }
  1326. X        else {
  1327. X            n_bits++;
  1328. X            if ( n_bits == maxbits )
  1329. X            maxcode = maxmaxcode;
  1330. X            else
  1331. X            maxcode = MAXCODE(n_bits);
  1332. X        }
  1333. X#ifdef DEBUG
  1334. X        if ( debug ) {
  1335. X        fprintf( stderr, "\nChange to %d bits\n", n_bits );
  1336. X        col = 0;
  1337. X        }
  1338. X#endif /* DEBUG */
  1339. X    }
  1340. X    } else {
  1341. X    /*
  1342. X     * At EOF, write the rest of the buffer.
  1343. X     */
  1344. X    if ( offset > 0 )
  1345. X        fwrite( buf, 1, (offset + 7) / 8, stdout );
  1346. X    bytes_out += (offset + 7) / 8;
  1347. X    offset = 0;
  1348. X    fflush( stdout );
  1349. X#ifdef DEBUG
  1350. X    if ( verbose )
  1351. X        fprintf( stderr, "\n" );
  1352. X#endif /* DEBUG */
  1353. X    if( ferror( stdout ) )
  1354. X        writeerr();
  1355. X    }
  1356. X}
  1357. X
  1358. X/*
  1359. X * Decompress stdin to stdout.  This routine adapts to the codes in the
  1360. X * file building the "string" table on-the-fly; requiring no table to
  1361. X * be stored in the compressed file.  The tables used herein are shared
  1362. X * with those of the compress() routine.  See the definitions above.
  1363. X */
  1364. X
  1365. Xdecompress() {
  1366. X    register char_type *stackp;
  1367. X    register int finchar;
  1368. X    register code_int code, oldcode, incode;
  1369. X
  1370. X    /*
  1371. X     * As above, initialize the first 256 entries in the table.
  1372. X     */
  1373. X    maxcode = MAXCODE(n_bits = INIT_BITS);
  1374. X    for ( code = 255; code >= 0; code-- ) {
  1375. X    tab_prefixof(code) = 0;
  1376. X    tab_suffixof(code) = (char_type)code;
  1377. X    }
  1378. X    free_ent = ((block_compress) ? FIRST : 256 );
  1379. X
  1380. X    finchar = oldcode = getcode();
  1381. X    if(oldcode == -1)    /* EOF already? */
  1382. X    return;            /* Get out of here */
  1383. X    putchar( (char)finchar );        /* first code must be 8 bits = char */
  1384. X    if(ferror(stdout))        /* Crash if can't write */
  1385. X    writeerr();
  1386. X    stackp = de_stack;
  1387. X
  1388. X    while ( (code = getcode()) > -1 ) {
  1389. X
  1390. X    if ( (code == CLEAR) && block_compress ) {
  1391. X        for ( code = 255; code >= 0; code-- )
  1392. X        tab_prefixof(code) = 0;
  1393. X        clear_flg = 1;
  1394. X        free_ent = FIRST - 1;
  1395. X        if ( (code = getcode ()) == -1 )    /* O, untimely death! */
  1396. X        break;
  1397. X    }
  1398. X    incode = code;
  1399. X    /*
  1400. X     * Special case for KwKwK string.
  1401. X     */
  1402. X    if ( code >= free_ent ) {
  1403. X            *stackp++ = finchar;
  1404. X        code = oldcode;
  1405. X    }
  1406. X
  1407. X    /*
  1408. X     * Generate output characters in reverse order
  1409. X     */
  1410. X#ifdef SIGNED_COMPARE_SLOW
  1411. X    while ( ((unsigned long)code) >= ((unsigned long)256) ) {
  1412. X#else
  1413. X    while ( code >= 256 ) {
  1414. X#endif
  1415. X        *stackp++ = tab_suffixof(code);
  1416. X        code = tab_prefixof(code);
  1417. X    }
  1418. X    *stackp++ = finchar = tab_suffixof(code);
  1419. X
  1420. X    /*
  1421. X     * And put them out in forward order
  1422. X     */
  1423. X    do
  1424. X        putchar ( *--stackp );
  1425. X    while ( stackp > de_stack );
  1426. X
  1427. X    /*
  1428. X     * Generate the new entry.
  1429. X     */
  1430. X    if ( (code=free_ent) < maxmaxcode ) {
  1431. X        tab_prefixof(code) = (unsigned short)oldcode;
  1432. X        tab_suffixof(code) = finchar;
  1433. X        free_ent = code+1;
  1434. X    } 
  1435. X    /*
  1436. X     * Remember previous code.
  1437. X     */
  1438. X    oldcode = incode;
  1439. X    }
  1440. X    fflush( stdout );
  1441. X    if(ferror(stdout))
  1442. X    writeerr();
  1443. X}
  1444. X
  1445. X/*****************************************************************
  1446. X * TAG( getcode )
  1447. X *
  1448. X * Read one code from the standard input.  If EOF, return -1.
  1449. X * Inputs:
  1450. X *     stdin
  1451. X * Outputs:
  1452. X *     code or -1 is returned.
  1453. X */
  1454. X
  1455. Xcode_int
  1456. Xgetcode() {
  1457. X    /*
  1458. X     * On the VAX, it is important to have the register declarations
  1459. X     * in exactly the order given, or the asm will break.
  1460. X     */
  1461. X    register code_int code;
  1462. X    static int offset = 0, size = 0;
  1463. X    static char_type buf[BITS];
  1464. X    register int r_off, bits;
  1465. X    register char_type *bp = buf;
  1466. X
  1467. X    if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) {
  1468. X    /*
  1469. X     * If the next entry will be too big for the current code
  1470. X     * size, then we must increase the size.  This implies reading
  1471. X     * a new buffer full, too.
  1472. X     */
  1473. X    if ( free_ent > maxcode ) {
  1474. X        n_bits++;
  1475. X        if ( n_bits == maxbits )
  1476. X        maxcode = maxmaxcode;    /* won't get any bigger now */
  1477. X        else
  1478. X        maxcode = MAXCODE(n_bits);
  1479. X    }
  1480. X    if ( clear_flg > 0) {
  1481. X            maxcode = MAXCODE (n_bits = INIT_BITS);
  1482. X        clear_flg = 0;
  1483. X    }
  1484. X    size = fread( buf, 1, n_bits, stdin );
  1485. X    if ( size <= 0 )
  1486. X        return -1;            /* end of file */
  1487. X    offset = 0;
  1488. X    /* Round size down to integral number of codes */
  1489. X    size = (size << 3) - (n_bits - 1);
  1490. X    }
  1491. X    r_off = offset;
  1492. X    bits = n_bits;
  1493. X#ifdef vax
  1494. X    asm( "extzv   r10,r9,(r8),r11" );
  1495. X#else /* not a vax */
  1496. X    /*
  1497. X     * Get to the first byte.
  1498. X     */
  1499. X    bp += (r_off >> 3);
  1500. X    r_off &= 7;
  1501. X    /* Get first part (low order bits) */
  1502. X#ifdef NO_UCHAR
  1503. X    code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
  1504. X#else
  1505. X    code = (*bp++ >> r_off);
  1506. X#endif /* NO_UCHAR */
  1507. X    bits -= (8 - r_off);
  1508. X    r_off = 8 - r_off;        /* now, offset into code word */
  1509. X    /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  1510. X    if ( bits >= 8 ) {
  1511. X#ifdef NO_UCHAR
  1512. X        code |= (*bp++ & 0xff) << r_off;
  1513. X#else
  1514. X        code |= *bp++ << r_off;
  1515. X#endif /* NO_UCHAR */
  1516. X        r_off += 8;
  1517. X        bits -= 8;
  1518. X    }
  1519. X    /* high order bits. */
  1520. X    code |= (*bp & rmask[bits]) << r_off;
  1521. X#endif /* vax */
  1522. X    offset += n_bits;
  1523. X
  1524. X    return code;
  1525. X}
  1526. X
  1527. Xchar *
  1528. Xrindex(s, c)        /* For those who don't have it in libc.a */
  1529. Xregister char *s, c;
  1530. X{
  1531. X    char *p;
  1532. X    for (p = NULL; *s; s++)
  1533. X        if (*s == c)
  1534. X        p = s;
  1535. X    return(p);
  1536. X}
  1537. X
  1538. X#ifdef DEBUG
  1539. Xprintcodes()
  1540. X{
  1541. X    /*
  1542. X     * Just print out codes from input file.  For debugging.
  1543. X     */
  1544. X    code_int code;
  1545. X    int col = 0, bits;
  1546. X
  1547. X    bits = n_bits = INIT_BITS;
  1548. X    maxcode = MAXCODE(n_bits);
  1549. X    free_ent = ((block_compress) ? FIRST : 256 );
  1550. X    while ( ( code = getcode() ) >= 0 ) {
  1551. X    if ( (code == CLEAR) && block_compress ) {
  1552. X           free_ent = FIRST - 1;
  1553. X           clear_flg = 1;
  1554. X    }
  1555. X    else if ( free_ent < maxmaxcode )
  1556. X        free_ent++;
  1557. X    if ( bits != n_bits ) {
  1558. X        fprintf(stderr, "\nChange to %d bits\n", n_bits );
  1559. X        bits = n_bits;
  1560. X        col = 0;
  1561. X    }
  1562. X    fprintf(stderr, "%5d%c", code, (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
  1563. X    }
  1564. X    putc( '\n', stderr );
  1565. X    exit( 0 );
  1566. X}
  1567. X
  1568. Xcode_int sorttab[1<<BITS];    /* sorted pointers into htab */
  1569. X
  1570. Xdump_tab()    /* dump string table */
  1571. X{
  1572. X    register int i, first;
  1573. X    register ent;
  1574. X#define STACK_SIZE    15000
  1575. X    int stack_top = STACK_SIZE;
  1576. X    register c;
  1577. X
  1578. X    if(do_decomp == 0) {    /* compressing */
  1579. X    register int flag = 1;
  1580. X
  1581. X    for(i=0; i<hsize; i++) {    /* build sort pointers */
  1582. X        if((long)htabof(i) >= 0) {
  1583. X            sorttab[codetabof(i)] = i;
  1584. X        }
  1585. X    }
  1586. X    first = block_compress ? FIRST : 256;
  1587. X    for(i = first; i < free_ent; i++) {
  1588. X        fprintf(stderr, "%5d: \"", i);
  1589. X        de_stack[--stack_top] = '\n';
  1590. X        de_stack[--stack_top] = '"';
  1591. X        stack_top = in_stack((htabof(sorttab[i])>>maxbits)&0xff, 
  1592. X                                     stack_top);
  1593. X        for(ent=htabof(sorttab[i]) & ((1<<maxbits)-1);
  1594. X            ent > 256;
  1595. X            ent=htabof(sorttab[ent]) & ((1<<maxbits)-1)) {
  1596. X            stack_top = in_stack(htabof(sorttab[ent]) >> maxbits,
  1597. X                        stack_top);
  1598. X        }
  1599. X        stack_top = in_stack(ent, stack_top);
  1600. X        fwrite( &de_stack[stack_top], 1, STACK_SIZE-stack_top, stderr);
  1601. X           stack_top = STACK_SIZE;
  1602. X    }
  1603. X   } else if(!debug) {    /* decompressing */
  1604. X
  1605. X       for ( i = 0; i < free_ent; i++ ) {
  1606. X       ent = i;
  1607. X       c = tab_suffixof(ent);
  1608. X       if ( isascii(c) && isprint(c) )
  1609. X           fprintf( stderr, "%5d: %5d/'%c'  \"",
  1610. X               ent, tab_prefixof(ent), c );
  1611. X       else
  1612. X           fprintf( stderr, "%5d: %5d/\\%03o \"",
  1613. X               ent, tab_prefixof(ent), c );
  1614. X       de_stack[--stack_top] = '\n';
  1615. X       de_stack[--stack_top] = '"';
  1616. X       for ( ; ent != NULL;
  1617. X           ent = (ent >= FIRST ? tab_prefixof(ent) : NULL) ) {
  1618. X           stack_top = in_stack(tab_suffixof(ent), stack_top);
  1619. X       }
  1620. X       fwrite( &de_stack[stack_top], 1, STACK_SIZE - stack_top, stderr );
  1621. X       stack_top = STACK_SIZE;
  1622. X       }
  1623. X    }
  1624. X}
  1625. X
  1626. Xint
  1627. Xin_stack(c, stack_top)
  1628. X    register c, stack_top;
  1629. X{
  1630. X    if ( (isascii(c) && isprint(c) && c != '\\') || c == ' ' ) {
  1631. X        de_stack[--stack_top] = c;
  1632. X    } else {
  1633. X        switch( c ) {
  1634. X        case '\n': de_stack[--stack_top] = 'n'; break;
  1635. X        case '\t': de_stack[--stack_top] = 't'; break;
  1636. X        case '\b': de_stack[--stack_top] = 'b'; break;
  1637. X        case '\f': de_stack[--stack_top] = 'f'; break;
  1638. X        case '\r': de_stack[--stack_top] = 'r'; break;
  1639. X        case '\\': de_stack[--stack_top] = '\\'; break;
  1640. X        default:
  1641. X         de_stack[--stack_top] = '0' + c % 8;
  1642. X         de_stack[--stack_top] = '0' + (c / 8) % 8;
  1643. X         de_stack[--stack_top] = '0' + c / 64;
  1644. X         break;
  1645. X        }
  1646. X        de_stack[--stack_top] = '\\';
  1647. X    }
  1648. X    return stack_top;
  1649. X}
  1650. X#endif /* DEBUG */
  1651. X
  1652. Xwriteerr()
  1653. X{
  1654. X    perror ( ofname );
  1655. X    unlink ( ofname );
  1656. X    exit ( 1 );
  1657. X}
  1658. X
  1659. Xcopystat(ifname, ofname)
  1660. Xchar *ifname, *ofname;
  1661. X{
  1662. X    struct stat statbuf;
  1663. X    int mode;
  1664. X    time_t timep[2];
  1665. X
  1666. X    fclose(stdout);
  1667. X    if (stat(ifname, &statbuf)) {        /* Get stat on input file */
  1668. X    perror(ifname);
  1669. X    return;
  1670. X    }
  1671. X    if ((statbuf.st_mode & S_IFMT/*0170000*/) != S_IFREG/*0100000*/) {
  1672. X    if(quiet)
  1673. X            fprintf(stderr, "%s: ", ifname);
  1674. X    fprintf(stderr, " -- not a regular file: unchanged");
  1675. X    exit_stat = 1;
  1676. X    } else if (statbuf.st_nlink > 1 && (! force) ) {
  1677. X    if(quiet)
  1678. X            fprintf(stderr, "%s: ", ifname);
  1679. X    fprintf(stderr, " -- has %d other links: unchanged",
  1680. X        statbuf.st_nlink - 1);
  1681. X    exit_stat = 1;
  1682. X    } else if (exit_stat == 2 && (!force)) { /* No compression: remove file.Z */
  1683. X    if(!quiet)
  1684. X        fprintf(stderr, " -- file unchanged");
  1685. X    } else {            /* ***** Successful Compression ***** */
  1686. X    exit_stat = 0;
  1687. X    mode = statbuf.st_mode & 07777;
  1688. X    if (chmod(ofname, mode))        /* Copy modes */
  1689. X        perror(ofname);
  1690. X    chown(ofname, statbuf.st_uid, statbuf.st_gid);    /* Copy ownership */
  1691. X    timep[0] = statbuf.st_atime;
  1692. X    timep[1] = statbuf.st_mtime;
  1693. X    utime(ofname, timep);    /* Update last accessed and modified times */
  1694. X    if (unlink(ifname))    /* Remove input file */
  1695. X        perror(ifname);
  1696. X    if(!quiet)
  1697. X        fprintf(stderr, " -- replaced with %s", ofname);
  1698. X    return;        /* Successful return */
  1699. X    }
  1700. X
  1701. X    /* Unsuccessful return -- one of the tests failed */
  1702. X    if (unlink(ofname))
  1703. X    perror(ofname);
  1704. X}
  1705. X/*
  1706. X * This routine returns 1 if we are running in the foreground and stderr
  1707. X * is a tty.
  1708. X */
  1709. Xforeground()
  1710. X{
  1711. X    if(bgnd_flag) {    /* background? */
  1712. X        return(0);
  1713. X    } else {            /* foreground */
  1714. X        if(isatty(2)) {        /* and stderr is a tty */
  1715. X            return(1);
  1716. X        } else {
  1717. X            return(0);
  1718. X        }
  1719. X    }
  1720. X}
  1721. X
  1722. Xonintr ( )
  1723. X{
  1724. X    unlink ( ofname );
  1725. X    exit ( 1 );
  1726. X}
  1727. X
  1728. Xoops ( )    /* wild pointer -- assume bad input */
  1729. X{
  1730. X    if ( do_decomp == 1 ) 
  1731. X        fprintf ( stderr, "uncompress: corrupt input\n" );
  1732. X    unlink ( ofname );
  1733. X    exit ( 1 );
  1734. X}
  1735. X
  1736. Xcl_block ()        /* table clear for block compress */
  1737. X{
  1738. X    register long int rat;
  1739. X
  1740. X    checkpoint = in_count + CHECK_GAP;
  1741. X#ifdef DEBUG
  1742. X    if ( debug ) {
  1743. X            fprintf ( stderr, "count: %ld, ratio: ", in_count );
  1744. X             prratio ( stderr, in_count, bytes_out );
  1745. X        fprintf ( stderr, "\n");
  1746. X    }
  1747. X#endif /* DEBUG */
  1748. X
  1749. X    if(in_count > 0x007fffff) {    /* shift will overflow */
  1750. X    rat = bytes_out >> 8;
  1751. X    if(rat == 0) {        /* Don't divide by zero */
  1752. X        rat = 0x7fffffff;
  1753. X    } else {
  1754. X        rat = in_count / rat;
  1755. X    }
  1756. X    } else {
  1757. X    rat = (in_count << 8) / bytes_out;    /* 8 fractional bits */
  1758. X    }
  1759. X    if ( rat > ratio ) {
  1760. X    ratio = rat;
  1761. X    } else {
  1762. X    ratio = 0;
  1763. X#ifdef DEBUG
  1764. X    if(verbose)
  1765. X        dump_tab();    /* dump string table */
  1766. X#endif
  1767. X     cl_hash ( (count_int) hsize );
  1768. X    free_ent = FIRST;
  1769. X    clear_flg = 1;
  1770. X    output ( (code_int) CLEAR );
  1771. X#ifdef DEBUG
  1772. X    if(debug)
  1773. X            fprintf ( stderr, "clear\n" );
  1774. X#endif /* DEBUG */
  1775. X    }
  1776. X}
  1777. X
  1778. Xcl_hash(hsize)        /* reset code table */
  1779. X    register count_int hsize;
  1780. X{
  1781. X#ifndef XENIX_16    /* Normal machine */
  1782. X    register count_int *htab_p = htab+hsize;
  1783. X#else
  1784. X    register j;
  1785. X    register long k = hsize;
  1786. X    register count_int *htab_p;
  1787. X#endif
  1788. X    register long i;
  1789. X    register long m1 = -1;
  1790. X
  1791. X#ifdef XENIX_16
  1792. X    for(j=0; j<=8 && k>=0; j++,k-=8192) {
  1793. X    i = 8192;
  1794. X    if(k < 8192) {
  1795. X        i = k;
  1796. X    }
  1797. X    htab_p = &(htab[j][i]);
  1798. X    i -= 16;
  1799. X    if(i > 0) {
  1800. X#else
  1801. X    i = hsize - 16;
  1802. X#endif
  1803. X     do {                /* might use Sys V memset(3) here */
  1804. X        *(htab_p-16) = m1;
  1805. X        *(htab_p-15) = m1;
  1806. X        *(htab_p-14) = m1;
  1807. X        *(htab_p-13) = m1;
  1808. X        *(htab_p-12) = m1;
  1809. X        *(htab_p-11) = m1;
  1810. X        *(htab_p-10) = m1;
  1811. X        *(htab_p-9) = m1;
  1812. X        *(htab_p-8) = m1;
  1813. X        *(htab_p-7) = m1;
  1814. X        *(htab_p-6) = m1;
  1815. X        *(htab_p-5) = m1;
  1816. X        *(htab_p-4) = m1;
  1817. X        *(htab_p-3) = m1;
  1818. X        *(htab_p-2) = m1;
  1819. X        *(htab_p-1) = m1;
  1820. X        htab_p -= 16;
  1821. X    } while ((i -= 16) >= 0);
  1822. X#ifdef XENIX_16
  1823. X    }
  1824. X    }
  1825. X#endif
  1826. X        for ( i += 16; i > 0; i-- )
  1827. X        *--htab_p = m1;
  1828. X}
  1829. X
  1830. Xprratio(stream, num, den)
  1831. XFILE *stream;
  1832. Xlong int num, den;
  1833. X{
  1834. X    register int q;            /* Doesn't need to be long */
  1835. X
  1836. X    if(num > 214748L) {        /* 2147483647/10000 */
  1837. X        q = num / (den / 10000L);
  1838. X    } else {
  1839. X        q = 10000L * num / den;        /* Long calculations, though */
  1840. X    }
  1841. X    if (q < 0) {
  1842. X        putc('-', stream);
  1843. X        q = -q;
  1844. X    }
  1845. X    fprintf(stream, "%d.%02d%%", q / 100, q % 100);
  1846. X}
  1847. X
  1848. Xversion()
  1849. X{
  1850. X    fprintf(stderr, "%s, patchlevel %d\n", version_id, PATCHLEVEL);
  1851. X    fprintf(stderr, "Options: ");
  1852. X#ifdef vax
  1853. X    fprintf(stderr, "vax, ");
  1854. X#endif
  1855. X#ifdef SHORTNAMES
  1856. X    fprintf(stderr,"SHORTNAMES, ");
  1857. X#endif
  1858. X#ifdef VOIDSIG
  1859. X    fprintf(stderr,"VOIDSIG, ");
  1860. X#endif
  1861. X#ifdef DIRENT
  1862. X    fprintf(stderr,"DIRENT, ");
  1863. X#endif
  1864. X#ifdef NO_UCHAR
  1865. X    fprintf(stderr, "NO_UCHAR, ");
  1866. X#endif
  1867. X#ifdef SIGNED_COMPARE_SLOW
  1868. X    fprintf(stderr, "SIGNED_COMPARE_SLOW, ");
  1869. X#endif
  1870. X#ifdef XENIX_16
  1871. X    fprintf(stderr, "XENIX_16, ");
  1872. X#endif
  1873. X#ifdef COMPATIBLE
  1874. X    fprintf(stderr, "COMPATIBLE, ");
  1875. X#endif
  1876. X#ifdef DEBUG
  1877. X    fprintf(stderr, "DEBUG, ");
  1878. X#endif
  1879. X#ifdef BSD4
  1880. X    fprintf(stderr, "BSD4, ");
  1881. X#endif
  1882. X    fprintf(stderr, "BITS = %d\n", BITS);
  1883. X}
  1884. END_OF_FILE
  1885. if test 42620 -ne `wc -c <'compress.c'`; then
  1886.     echo shar: \"'compress.c'\" unpacked with wrong size!
  1887. fi
  1888. # end of 'compress.c'
  1889. fi
  1890. echo shar: End of archive 1 \(of 2\).
  1891. cp /dev/null ark1isdone
  1892. MISSING=""
  1893. for I in 1 2 ; do
  1894.     if test ! -f ark${I}isdone ; then
  1895.     MISSING="${MISSING} ${I}"
  1896.     fi
  1897. done
  1898. if test "${MISSING}" = "" ; then
  1899.     echo You have unpacked both archives.
  1900.     rm -f ark[1-9]isdone
  1901. else
  1902.     echo You still need to unpack the following archives:
  1903.     echo "        " ${MISSING}
  1904. fi
  1905. ##  End of shell archive.
  1906. exit 0
  1907.  
  1908.  
  1909. -- 
  1910. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1911. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1912. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1913. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1914.  
  1915. exit 0 # Just in case...
  1916. -- 
  1917. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1918. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1919. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1920. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1921.